﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using MiniStock.Infrastructure.Configurator;
using MiniStock.Infrastructure.Queue;

namespace MiniStock.Infrastructure
{
    public class MiniStockContext: IDisposable
    {
        private static readonly object GlobalRootContainerLock = new object();
        private static volatile IUnityContainer GlobalRootContainer;

        public static Action<IUnityContainer> OnConfigureGlobalContainer;
        public static Action<IUnityContainer> OnConfigureContainer;

        [ThreadStatic] 
        private static MiniStockContext _current;
        
        public static MiniStockContext Current { get { return _current; } protected internal set { _current = value; } }

        protected internal void AssertRootContainer()
        {
            if(GlobalRootContainer == null)
            {
                lock(GlobalRootContainerLock)
                {
                    if(GlobalRootContainer == null)
                    {
                        var container = new UnityContainer();
                        if(OnConfigureGlobalContainer != null)
                            OnConfigureGlobalContainer(container);
                        GlobalRootContainer = container;
                    }
                }
            }
        }

        protected internal MiniStockContext()
        {
            AssertRootContainer();

            RootContainer = GlobalRootContainer.CreateChildContainer();
            if (OnConfigureContainer != null)
                OnConfigureContainer(RootContainer);
        }

        public IUnityContainer RootContainer { get; set; }

        public void Dispose()
        {
            Dispose(true);
        }

        ~MiniStockContext()
        {
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if(disposing)
                RootContainer.Dispose();
        }
    }

    public class MiniStockContextScope: IDisposable
    {
        private MiniStockContext _previous; 
        public MiniStockContextScope()
        {
            _previous = MiniStockContext.Current;
            MiniStockContext.Current = new MiniStockContext();
        }

        public void Dispose()
        {
            MiniStockContext.Current.Dispose();
            MiniStockContext.Current = _previous;
        }
    }
}
